﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;


namespace community_severvice_exchange
{
    [Serializable]
    public class UserRegister
    {
        private string _usr;
        private string _psw;
        private User user = null;
        private Boolean isExist = false;
        private Boolean flag = false;
        public List<User> list_users = new List<User>();

        List<Feedback> list_feedback = new List<Feedback>();
        List<DateTime> list_date = new List<DateTime>();
        List<Skills> list_skill = new List<Skills>();  

        public List<Skills> loadSkill()
        {
            Skills skills = null;
            using (FileStream f = new FileStream("skills.txt", FileMode.Open, FileAccess.Read))
            {
                using (StreamReader sr = new StreamReader(f))
                {
                    string line = null;
                    string[] temp = null;
                    while ((line = sr.ReadLine()) != null)
                    {
                        temp = line.Split('+');
                        skills = new Skills();
                        skills.ID = temp[0];
                        skills.Hour = temp[1];
                        skills.Item = temp[2];
                        skills.Desc = temp[3];
                        list_skill.Add(skills);
                    }
                }
            }
            return list_skill;
        }
        public void saveSkills() 
        {
            this.list_skill = loadSkill();
            try
            {
                using (FileStream f = new FileStream("skills.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(f, list_skill);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
       
        public List<Skills> loadSkillWithProvider()
        {
            List<Skills> list_skill_provider = null;
            try
            {
                using (FileStream f = new FileStream("skillsWithProvider.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    list_skill_provider = (List<Skills>)bf.Deserialize(f);
                }
            }
            catch (Exception e) 
            { 
                Console.WriteLine(e.Message); 
            }
            return list_skill_provider;
        }

        public void saveSkillsWithProvider(User provider,int[] skillID) 
        {
            List<Skills> list_providerSkill = loadSkillWithProvider();
            this.list_skill = loadSkill();
           
            foreach (int i in skillID)
            {
                list_skill[i-1].Provider=provider;
                list_providerSkill.Add(list_skill[i-1]);
            }
            using (FileStream f = new FileStream("skillsWithProvider.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(f,list_providerSkill);
            }
        }
        
        public bool addUser(string usr, string psw, string address, int[] skillID)
        {
            this._usr = usr;
            this._psw = psw;

            if (!checkUser(_usr, _psw))
            {
                this.user = new User(_usr, _psw);
                user.Address = address;
                foreach (int i in skillID)
                    user.skills.Add(i);
                saveSkillsWithProvider(this.user, skillID);
                saveUser(this.user);
                using (FileStream f = new FileStream("users.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    using (StreamWriter sw = new StreamWriter(f))
                    {
                        sw.BaseStream.Seek(0, SeekOrigin.End);
                        sw.Write(_usr);
                        sw.Write("+");
                        sw.Write(_psw + "\r\n");
                        sw.Flush();
                    }
                }
                this.flag = true;
            }
            return flag;
        }

        public void deleteUser(string username) 
        {
            list_users = loadUser();
            foreach (User u in list_users)
            {
                if (u.Name.Equals(username))
                {
                    list_users.Remove(u);
                    try
                    {
                        using (FileStream f = new FileStream("users.bin", FileMode.Open, FileAccess.ReadWrite))
                        {
                            BinaryFormatter bf = new BinaryFormatter();
                            bf.Serialize(f, list_users);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    break;
                }
                else 
                {
                    Console.WriteLine("not exist!");
                }
            }
        }

        /*
        public bool addUser(string usr, string psw,string address,int[] skillID)
        {
            this._usr = usr;
            this._psw = psw;

            if (!checkUser(_usr,_psw))
            {
                this.user = new User(_usr, _psw);
                user.Address = address;
                foreach (int i in skillID)
                    user.skills.Add(i);

                saveUser(this.user);
                using (FileStream f = new FileStream("users.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    using (StreamWriter sw = new StreamWriter(f))
                    {
                        sw.BaseStream.Seek(0, SeekOrigin.End);
                        sw.Write(_usr);
                        sw.Write("+");
                        sw.Write(_psw + "\r\n");
                        sw.Flush();
                    }
                }
                this.flag = true;
            }
            return flag;
        }
        */
        private bool checkUser(string usr,string psw) 
        {
                using (FileStream f = new FileStream("users.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    
                    StreamReader sr = new StreamReader(f);

                    string[] temp = null;
                    string line = null;
                    while ((line = sr.ReadLine()) != null)
                    {
                        temp = line.Split('+');
                        if (usr.Equals(temp[0]))
                        {
                            isExist = true; break;                          
                        }
                        else
                        {
                            isExist = false;
                        }                      
                    }           
                }
                return isExist;
        }

        public void saveUser(User user)
        {
            this.list_users=loadUser();
            this.list_users.Add(user);
            try
            {
                using (FileStream f = new FileStream("users.bin", FileMode.Open, FileAccess.ReadWrite))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(f, list_users);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
      
        public List<User> loadUser()
        {
            List<User> list =null;
            using (FileStream f = new FileStream("users.bin", FileMode.Open, FileAccess.ReadWrite))
            {
                BinaryFormatter bf = new BinaryFormatter();
                list = (List<User>)bf.Deserialize(f);              
            }
            return list;
        }

        public User getUser(string name)
        {
            if (true)
            {
                list_users = loadUser();
                foreach (User u in list_users)
                {
                    if (u.Name.Equals(name)) 
                    {
                        this.user = u;
                        break;
                    }                   
                }

            }
            return this.user;
        }

        public void updateListWithProvider(User user) 
        {
            List<Skills> list_providerSkill = loadSkillWithProvider();
            int[] skillid = user.skills.ToArray();
            
            for (int i = list_providerSkill.Count; i > 0; i--)
            {
                if (list_providerSkill[i-1].Provider.Name.Equals(user.Name))
                {
                    
                    list_providerSkill.RemoveAt(i-1);
                    using (FileStream f = new FileStream("skillsWithProvider.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        bf.Serialize(f, list_providerSkill);
                    }
                }
                
            }

            saveSkillsWithProvider(user, skillid);
        }

        public void updateList(User user) 
        {
            this.list_users = loadUser();
            for (int i = list_users.Count; i> 0; i--)
            {
                if (list_users[i-1].Name.Equals(user.Name))
                {
                    list_users.Remove(list_users[i-1]);
                    list_users.Add(user);
                    try
                    {
                        using (FileStream f = new FileStream("users.bin", FileMode.Open, FileAccess.ReadWrite))
                        {
                            BinaryFormatter bf = new BinaryFormatter();
                            bf.Serialize(f, list_users);
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                    break;
                }
            }
            updateListWithProvider(user);            
        }

        public List<Skills> match(User match_user,int[] needID) 
        {
            List<Skills> list_providerSkill = loadSkillWithProvider();

            List<Skills> list_match_skill = new List<Skills>();
            List<Skills> list_result = new List<Skills>();

            List<int> match_need = new List<int>();
            List<int> user_skill = new List<int>();

            list_skill=loadSkill();
            user_skill = match_user.skills;

            User u = null;

            foreach (int x in needID)
            {
                foreach (Skills skill in list_providerSkill)
                {
                    if (skill.ID.Equals(list_skill[x - 1].ID))
                    {
                        //matched skill in other user
                        list_match_skill.Add(skill);
                    }
                }
            }
            foreach (Skills match_skill in list_match_skill)
            {
              
                match_need.AddRange(match_skill.Provider.user_needs);
               
                foreach (int user_skillID in user_skill)
                {
                    foreach (int user_needID in match_need)
                    {
                        if (user_skillID == user_needID)
                        {
                            list_result.Add(match_skill);
                        }
                    }
                }
                
            }
            return list_match_skill;
        }

        public List<Skills> match(User match_user,int needID) 
        {
            List<Skills> list_provider_skill = loadSkillWithProvider();
            List<Skills> list_result = new List<Skills>();
            User u = match_user;

            foreach (Skills skill in list_provider_skill)
            {
                if (skill.ID.Equals(needID.ToString())&!(skill.Provider.Name.Equals(u.Name)))
                {
                    foreach (int skillid in u.skills)
                    {
                        foreach (int needid in skill.Provider.user_needs)
                        {
                            if (skillid == needid)
                                list_result.Add(skill);
                            break;
                        }
                    }
                }
            }
            return list_result;
        }

        public void addNeed(User current_user,int needID,System.DateTime date)
        {
             List<string> list_date = new List<string>();
           if(!current_user.user_needs.Contains(needID)){
                    string string_date = date.Date.ToString();
                   // list_date.Add(string_date);
                    current_user.list_date.Add(string_date);
                    current_user.user_needs.Add(needID);
                    updateList(current_user);
                }
            
           
            
        }

        public void addNeed(User current_user, int needID)
        {
            //current_user.user_needs = new List<int>();
          
                if (!current_user.user_needs.Contains(needID))
                    current_user.user_needs.Add(needID);
                
            updateList(current_user);
        }

        public void addFeedback(User user,Skills matched_skill,string comment,int grade)
        {
            Feedback feedback = new Feedback(matched_skill, comment, grade);
            list_feedback.Add(feedback);
            user.list_feedback = list_feedback;
            saveUser(user);
        }

        public List<Skills> loadMatched(User u) 
        {
            List<Skills> list = null;
            using (FileStream f = new FileStream(u.Name + "saveMatched.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                if (f.Length == 0)
                {
                    List<Skills> temp = new List<Skills>();
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(f, temp);
                }
                else 
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    list = (List<Skills>)bf.Deserialize(f);
                }   
                
            }
            return list;
        }

        public void saveMatched(User u,Skills matchedskill)
        {
            List<Skills> list = loadMatched(u);
            list.Add(matchedskill);
            try
            {
                using (FileStream f = new FileStream(u.Name+"saveMatched.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(f,list);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        public void initSaveMatched(User u) 
        {
            List<Skills> list = new List<Skills>();
            try
            {
                using (FileStream f = new FileStream(u.Name + "saveMatched.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
                {
                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(f, list);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }
    }
}
